﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Compilador
{
    public class Program
    {
        public static void Main(string[] args)
        {


            //string[] assembler = { "DATA:", "var1 5", "var2 3", "CODE:", "MOV A,(var1)", "MOV B,(var2)", "CMP A,B", "JGE amayorb", "nada:", "JMP nada", "amayorb:", "MOV A,(var2)", "JMP amayorb" };
            string[] assembler = {"DATA:","var1 2","var2 4","CODE:","MOV A,(var1)","MOV B,(var2)","CMP A,B","JLT amenorb","nada:","JMP nada","amenorb:","MOV A,(var2)","JMP amenorb" };
            //string[] assembler = { "DATA:","var1 1","var2 2","CODE:","MOV A,(var1)","MOV B,(var2)","INC A","CMP A,B","JEQ hola","nada:","JMP nada","hola:","SUB A,B","fin:","JMP fin"}; 
            string[] assemblerData= Data(assembler);
             string  [] assemblerCode= Code(assembler);
                        
             string[] desifrado = DesifrarCode(assemblerCode, assemblerData);
             for (int i = 0; i < desifrado.Length; i++)
             {
                 Console.WriteLine(desifrado[i]);
             }
             Console.ReadLine();
             
            Console.ReadLine();
           

            
        }

        public static string[] Data(string[] palabras)
        {
            int ndata = 0;
            int ncode = 0;


            for (int i = 0; i < palabras.Length; i++)
            {
                if (palabras[i].Contains("DATA"))
                {
                    ndata = i;
                }
            }

            for (int i = 0; i < palabras.Length; i++)
            {
                if (palabras[i].Contains("CODE"))
                {
                    ncode = i;
                }
            }

            string[] data = new string[ncode - 1];

            for (int j = 0; j < ncode - 1; j++)
            {

                data[j] = palabras[j + 1];

            }

            return data;
        }



        public static string[] Code(string[] palabras)
        {
            int ndata = 0;
            int ncode = 0;

            string[] data = Data(palabras);

            int b = 0;

            string[] temp = new string[2 * data.Length];

            foreach (string dato in data)
            {

                int n = dato.IndexOf(" ");
                string nombre = dato.Substring(0, n);
                string numero = dato.Substring(n + 1);

                temp[b] = "MOV B," + numero;
                temp[b + 1] = "MOV (" + nombre + "),B";



                b = b + 2;
            }


            for (int i = 0; i < palabras.Length; i++)
            {
                if (palabras[i].Contains("DATA"))
                {
                    ndata = i;
                }
            }

            for (int i = 0; i < palabras.Length; i++)
            {
                if (palabras[i].Contains("CODE"))
                {
                    ncode = i;
                }
            }

            string[] code = new string[palabras.Length - ncode - 1 + temp.Length];

            for (int j = 0; j < temp.Length; j++)
            {
                code[j] = temp[j];
            }

            for (int j = temp.Length; j < palabras.Length - ncode + temp.Length - 1; j++)
            {

                code[j] = palabras[j];
            }

            int a = 0;
       /*     for (int i = 0; i < code.Length; i++)
            {
                if (code[i].Contains("JMP"))
                {
                    a++;
                }
            }*/

           string[] tempo = new string[code.Length + a];

      /*       int d = 0;
            int e = 0;
            while (d < tempo.Length)
            {
                if (code[e].Contains("JMP"))
                {
                    int c = code[e].IndexOf(" ");
                    string sub = code[e].Substring(c + 1);
                    tempo[d] = code[e];
                    tempo[d + 1] = "JEQ " + sub;
                    d = d + 2;
                    e++;
                }
                else
                {
                    tempo[d] = code[e];
                    d++;
                    e++;
                }
            }*/
            return code;
        }

        public static string[] DesifrarCode(string[] Code,string []Data)
        {
            int m = 0;
            for (int i = 0; i < Code.Length; i++)
            {
                if (Code[i].Contains("JMP"))
                {
                    m++;
                   
                }
                m++;

            }
            string[] Desifrado = new string[m];
            int j = 0;
            for (int i=0; i < Code.Length; i++)
            {
                
                    Desifrado[j] = DesifrarInstruccion(Code[i], Data, Code);
                    if (Code[i].Contains("JMP"))
                    {
                        j++;
                        
                            int c = Code[i].IndexOf(" ");
                            string sub = Code[i].Substring(c + 1);
                            Desifrado[j] = DesifrarInstruccion("JEQ " + sub,Data,Code);
                           
                        
 
                    }
                    j++;
                
            }
            int k=0;
            for (int i = 0; i <Desifrado.Length; i++)
            {
                if (Desifrado[i].Length!=0)
                {
                Desifrado[k] = Desifrado[i];
                k++;
                }
            }
            string[] Desifrado1 = new string[k];
            for (int i = 0; i < k; i++)
            {
                
                    Desifrado1[i] = Convert.ToString(i) + Desifrado[i];
              
                
            }
          

            return Desifrado1;
        }


        public static string DesifrarInstruccion(string instruccion,string []Data,string []Code)
        {
            string ins = instruccion;
            string señalControl="";
            if (instruccion.Contains("MOV"))
            {
                if (instruccion.Contains("A,B"))
                {
                    señalControl += "0000000001000101000000000";

                }
                else if (instruccion.Contains("B,A"))
                {
                    señalControl += "0000000001010010000000000";

                }                
                else if (instruccion.Contains("A,(B)"))
                {
                    señalControl += "0000001001100101000000000";
                }
                else if (instruccion.Contains("B,(B)"))
                {
                    señalControl += "0000001001100110000000000";

                }
                else if (instruccion.Contains("(B),A"))
                {
                    señalControl += "0000001011010001000000000";
                }
                    
                else if (instruccion.Contains("A,("))
                {
                    señalControl += "00000000011001010" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length),Data);
                }
                 
                else if (instruccion.Contains("B,("))
                {
                    señalControl += "00000000011001100" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length),Data);
                }
                
                else if (instruccion.Contains("),A"))
                {
                    señalControl += "00000000110100000" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"),instruccion.Substring(instruccion.IndexOf(")")).Length).Length),Data);
                }  
                
                else if(instruccion.Contains("),B"))
                {
                    señalControl += "00000000110001000" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"),instruccion.Substring(instruccion.IndexOf(")")).Length).Length),Data);
                }
                else if (instruccion.Contains("A,"))
                {
                    señalControl += "00000000011101010" + EntregarLiteral(instruccion.Substring(instruccion.IndexOf(",") + 1));
                }

                else if (instruccion.Contains("B,"))
                {
                    señalControl += "00000000011101100" + EntregarLiteral(instruccion.Substring(instruccion.IndexOf(",") + 1));
                                   
                }
             
            }
            else if (instruccion.Contains("ADD"))
            {
                if (instruccion.Contains("A,B"))
                {
                    señalControl += "0000000001000001000000000";

                }
                else if (instruccion.Contains("B,A"))
                {
                    señalControl += "0000000001000010000000000";

                }
                else if (instruccion.Contains("A,(B)"))
                {
                    señalControl += "0000001001100010000000000";
                }
                else if (instruccion.Contains("A,("))
                {
                    señalControl += "00000000011000010" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length),Data);
                }
                else if (instruccion.Contains("A,"))
                {
                    señalControl += "00000000011100010" + EntregarLiteral(instruccion.Substring(instruccion.IndexOf(",") + 1));
                }
                else if (instruccion.Contains("A ( "))
                {
                    señalControl += "00000000110000000" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length), Data);
                }


            }
            else if (instruccion.Contains("SUB"))
            {
                if (instruccion.Contains("A,B"))
                {
                    señalControl += "0000000000000001000000000";

                }
                else if (instruccion.Contains("B,A"))
                {
                    señalControl += "0000000000000010000000000";

                }
                else if (instruccion.Contains("A,(B)"))
                {
                    señalControl += "0000001000100001000000000";
                }
                else if (instruccion.Contains("A,("))
                {
                    señalControl += "00000000001000010" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length),Data);
                }
                else if (instruccion.Contains("A,"))
                {
                    señalControl += "00000000001100010" + EntregarLiteral(instruccion.Substring(instruccion.IndexOf(",") + 1));
                }
                else if (instruccion.Contains("A ( "))
                {
                    señalControl += "00000000100000000" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length),Data);
                }
            }
            else if (instruccion.Contains("INC"))
            {
                if (instruccion.Contains("A"))
                {
                    señalControl += "0000000001110001000000001";

                }
                else if (instruccion.Contains("B"))
                {
                    señalControl += "0000000001001010000000000";

                }
            }
            else if (instruccion.Contains("DEC A"))
            {
                señalControl += "0000000000110001000000001";
            }
            else if (instruccion.Contains("JMP"))
            {
                señalControl += "0000000001010100000000000";
            }
            else if (instruccion.Contains("JEQ"))
            {
                señalControl += "00000000000000001" + EntregarLabel(instruccion.Substring(instruccion.IndexOf("JEQ") + 4),Code);
            }
            else if (instruccion.Contains("JNE"))
            {
                señalControl += "00000100000000001" + EntregarLabel(instruccion.Substring(instruccion.IndexOf("JNE") + 4),Code);
            }
            else if (instruccion.Contains("CMP"))
            {
                if (instruccion.Contains("A,B"))
                {
                    señalControl += "0000000000000000000000000";
                }
                else if (instruccion.Contains("A,"))
                {
                    señalControl += "00000000001100000" + EntregarLiteral(instruccion.Substring(instruccion.IndexOf(",") + 1));
                }
            }
            else if (instruccion.Contains("JGE"))
            {
                señalControl += "10000000000000001" + EntregarLabel(instruccion.Substring(instruccion.IndexOf("JGE") + 4),Code);
            }
            else if (instruccion.Contains("JLT"))
            {
                señalControl += "10000100000000001" + EntregarLabel(instruccion.Substring(instruccion.IndexOf("JLT") + 4),Code);
            }
            else if (instruccion.Contains("CALL"))
            {
                señalControl += "01100001100000001" + EntregarLabel(instruccion.Substring(instruccion.IndexOf("CALL") + 5),Code);
            }
            else if (instruccion.Contains("RET"))
            {
                señalControl += "0001100100000000000000000";
            }
            else if (instruccion.Contains("PUCH"))
            {
                if (instruccion.Contains("A"))
                {
                    señalControl += "0010000111010000000000000";
                }
                else if (instruccion.Contains("B"))
                {
                    señalControl += "0010000111000100000000000";
                }
                
            }
            else if (instruccion.Contains("POP"))
            {
                if (instruccion.Contains("A"))
                {
                    señalControl += "0001000101100101000000000";
                }
                else if (instruccion.Contains("B"))
                {
                    señalControl += "0001000101100110000000000";
                }
                
            }
            /***********************************************************/
            else if (instruccion.Contains("IN"))
            {
                if (instruccion.Contains("A"))
                {
                    señalControl += "0000000000011101000000000";
                }
                else if (instruccion.Contains("B"))
                {
                    señalControl += "0000000000011110000000000";
                }

            }
            else
            {
                return señalControl;
            }
            return "=> \""+señalControl+"\"";


        }
        public static string EntregarLiteral (string instruccion)
        {
            if (instruccion.Contains("b"))
            {
                instruccion = instruccion.Substring(0,instruccion.Length - instruccion.Substring(instruccion.IndexOf("b")).Length);
                if (instruccion.Length < 8)
                {
                    for (int k = 0; instruccion.Length < 8; k++)
                    {
                        instruccion = "0" + instruccion;
                    }
                }
                
            }

            else if(instruccion.Contains("h"))
            {
                instruccion = instruccion.Substring(0, instruccion.Length - instruccion.Substring(instruccion.IndexOf("h")).Length);
                instruccion = decOrHexToBin(instruccion, 1);
            }
            else
            {
                instruccion = decOrHexToBin(instruccion, 0);

            }
            


            return instruccion;
        }
        public static string EntregarDir(string instruccion,string []Data)
        {
             
            string aux="";
            for (int i = 0; i < Data.Length; i++)
            {
                if (Data[i].Contains(instruccion))
                {
                    aux = Data[i];
                    aux=aux.Remove(0,instruccion.Length);
                    aux = decOrHexToBin(Convert.ToString(i), 0);
                    return  aux;
                }

            }
           
            
            return aux;
        }
        public static string EntregarLabel(string instruccion,string []Code)
        {
            string dirLabel = "";
            
            for (int i = 0; i < Code.Length;i++ )
            {
                if (Code[i].Contains(instruccion+":"))
                {
                    dirLabel=Code[i];
                    dirLabel = decOrHexToBin(Convert.ToString(i), 0);
                    return dirLabel;
                }
                
            }
           
            return dirLabel;
        }
        public static string decOrHexToBin(string numS, int mode)
        {
            //mode 0 es de decimal, mode 1 es de hexadecimal
            string inBinary = "";
            int numI;
            string aux = "";
            if (mode == 0)
            {
                Int32.TryParse(numS, out numI);
                aux = Convert.ToString((sbyte)numI, 2);
            }
            else
            {
                numI = Int32.Parse(numS, System.Globalization.NumberStyles.HexNumber);
                aux = Convert.ToString((sbyte)numI, 2);
            }
            //retornamos 0 si el numero lo es
            if (numI == 0)
            {
                inBinary = "00000000";
            }
            //convertidoms a sByte, con signo y luego completamos los 0 para que sean 8 bits
            else if (numI > 0)
            {
                if (aux.Length > 8)
                {
                    inBinary = aux.Substring(8, 8);
                }
                else
                {
                    while (aux.Length < 8)
                    {
                        aux = "0" + aux;
                    }
                    inBinary = aux;
                }
            }
            //convertimos a Sbyte, con signo y luego truncamos para que sean solo 8 bits o agregamos cero si es de menos
            else
            {
                if (aux.Length > 8)
                {
                    inBinary = aux.Substring(8, 8);
                }
                else
                {
                    while (aux.Length < 8)
                    {
                        aux = "1" + aux;
                    }
                }
            }
            return inBinary;
        }
    }
}
